package cn.piesat.service.impl;

import cn.piesat.dto.PiesatResourceInfoDTO;
import cn.piesat.mapper.MenuMapper;
import cn.piesat.util.TreeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import cn.piesat.dao.PiesatMenuInfoDAO;
import cn.piesat.dao.PiesatResourceInfoDAO;
import cn.piesat.dao.PiesatRoleMenuDAO;
import cn.piesat.dto.PiesatMenuInfoDTO;
import cn.piesat.service.intf.MenuService;
import cn.piesat.vo.menu.AddMenuVO;
import cn.piesat.vo.menu.MenuDetailVO;
import cn.piesat.vo.menu.UpdateMenuVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * 菜单服务层逻辑实现
 *
 * @author xhl
 */
@Service
public class MenuServiceImpl implements MenuService {

    @Autowired
    private PiesatMenuInfoDAO piesatMenuInfoDAO;

    @Autowired
    private PiesatResourceInfoDAO piesatResourceInfoDAO;

    @Autowired
    private PiesatRoleMenuDAO piesatRoleMenuDAO;

    /**
     * 添加菜单信息参数，菜单名称不能重复
     * @param dto 添加菜单信息参数对象
     * @return
     */
    @Override
    public Map<String, String> add(AddMenuVO dto) {
        Map<String,String> resultMap = new HashMap<>();
        PiesatMenuInfoDTO existDO = piesatMenuInfoDAO.findByName(dto.getName());
        if (existDO != null) {
            resultMap.put("success","false");
            resultMap.put("message","添加失败，菜单名称已存在");
            return resultMap;
        }
        PiesatMenuInfoDTO menuDO = MenuMapper.INSTANCE.addMenuDtoToMenuDo(dto);
        menuDO.setCreateTime(new Date());
        piesatMenuInfoDAO.save(menuDO);
        resultMap.put("success","true");
        resultMap.put("message","添加成功");
        return resultMap;
    }

    /**
     * 修改菜单信息参数对象，菜单名称不能重复
     * @param updateDTO 修改菜单信息参数对象
     * @return
     */
    @Override
    public Map<String, String> update(UpdateMenuVO updateDTO) {
        Map<String,String> resultMap = new HashMap<>();
        PiesatMenuInfoDTO existMenuDO = piesatMenuInfoDAO.findByName(updateDTO.getName());
        if (existMenuDO != null && !existMenuDO.getId().equals(updateDTO.getId())) {
            resultMap.put("success","false");
            resultMap.put("message","修改失败，菜单名称已存在");
            return resultMap;
        }
        PiesatMenuInfoDTO piesatMenuInfoDTO = MenuMapper.INSTANCE.updateMenuDtoToMenuDo(updateDTO);
        piesatMenuInfoDAO.save(piesatMenuInfoDTO);
        resultMap.put("success","true");
        resultMap.put("message","修改成功");
        return resultMap;
    }

    @Override
    public MenuDetailVO getOne(String id) {
        return piesatMenuInfoDAO.findById(id)
                .map(MenuMapper.INSTANCE::menuDoToMenuDetailVo)
                .orElse(null);
    }

    @Override
    public JSONArray list() {
        //因为要保证顺序，在TreeUtil.listToTree方法中的原理都是在List后追加，所以只要保证传入的集合为有序的，那么树形结构也是有序的
        List<PiesatMenuInfoDTO> menuList = piesatMenuInfoDAO.findAllByOrderBySeq();
        List<MenuDetailVO> formatMenuList = menuList.stream()
                .map(MenuMapper.INSTANCE::menuDoToMenuDetailVo)
                .collect(Collectors.toList());
        JSONArray menuArray = JSON.parseArray(JSON.toJSONString(formatMenuList));
        return TreeUtil.listToTree(menuArray,"id","pid","children");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, String> deleteOne(String id) {
        Map<String,String> resultMap = new HashMap<>();
        //查找该节点的所有子节点，最后加上本身
        List<String> allList = piesatMenuInfoDAO.findByPid(id).stream().map(p ->p.getId()).collect(toList());
        List<String> list = new ArrayList<>();
        List<String> list1 = new ArrayList<>();
        List<String> menuids = findChildren(list,allList);
        list1.addAll(menuids);
        list1.addAll(allList);
        list1.add(id);
        //删除菜单和资源关系
        piesatResourceInfoDAO.deleteAllByMenuIdIn(list1);
        //删除菜单信息
        piesatMenuInfoDAO.deleteAllByIdIn(list1);
        //删除菜单和角色绑定关系
        piesatRoleMenuDAO.deleteAllByMenuIdIn(list1);
        resultMap.put("success","true");
        resultMap.put("message","删除成功");
        return resultMap;
    }


    private List<String> findChildren(List<String> list,List<String> allList){
            List<String> menList = piesatMenuInfoDAO.findAllByPidIn(allList).stream().map(p ->p.getId()).collect(toList());
            if(menList.size()==0 || menList ==null){

            }else{
                list.addAll(menList);
                findChildren(list,menList);
            }
        return list;
    }
}
